package cn.dengta.webapp.trade.entity;

import java.math.BigDecimal;
import java.util.Date;
import java.util.Map;

import cn.dengta.common.model.BizFlag;
import cn.dengta.common.model.Messager;
import cn.dengta.context.model.MessagerStatus;
import cn.dengta.context.model.WesKit;
import cn.dengta.webapp.base.entity.TimeBasedEntity;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.Accessors;
import me.codeplayer.util.CollectionUtil;

import static cn.dengta.webapp.trade.model.TradeTypeCore.calc;

/**
 * 用户钻石
 *
 * @author yuqidi
 * @since 2022-03-14
 */
@Setter
@Getter
@Accessors(chain = true)
@TableName("tr_user_coin")
public class UserCoin extends TimeBasedEntity implements BizFlag.WritableBizFlag {

	/** 已充值过 */
	public static final long BIZ_FLAG_RECHARGED = 1L;

	/** 用户ID（=主键ID） */
	private Long userId;
	/** 资金总额（ <code> = activeAmount + frozenAmount</code> ） */
	protected Integer totalAmount;
	/** 可用余额（包含 <code>freePart</code>） */
	protected Integer activeAmount;
	/** 冻结金额（因某些业务需要，需提前冻结的钻石额度。出于性能考虑，可能会放在 Redis 里面，数据可能会有一定的延迟） */
	protected Integer frozenAmount;
	/** 赠送部分（参与平台活动免费赠送的钻石额度） */
	protected Integer freePart;
	//	/** 总的信用钻石（=activeCredit + frozenCredit） */
	//	protected Integer totalCredit;
	//	/** 可用的信用钻石 */
	//	protected Integer activeCredit;
	//	/** 冻结信用钻石数 */
	//	protected Integer frozenCredit;
	/** 累计钻石充值金额 */
	protected BigDecimal totalRecharge;
	/** 总充值金额（包含VIP） */
	protected BigDecimal allCoinRecharge;

	/** 基于位运算的业务标识 */
	protected long bizFlag;

	public UserCoin init(Long userId, Date now) {
		this.id = userId;
		this.userId = userId;
		this.totalAmount = frozenAmount = activeAmount = freePart = 0;
		this.totalRecharge = allCoinRecharge = BigDecimal.ZERO;
		super.initTime(now);
		return this;
	}

	public Integer opTotalAmount(char operator, Integer coin) {
		return totalAmount = calc(totalAmount, operator, coin);
	}

	public Integer opActiveAmount(char operator, Integer coin) {
		return activeAmount = calc(activeAmount, operator, coin);
	}

	public Integer opFrozenAmount(char operator, Integer coin) {
		return frozenAmount = calc(frozenAmount, operator, coin);
	}

	public Integer opFreePart(char operator, Integer coin) {
		return freePart = calc(freePart, operator, coin);
	}

	public void setBizFlag(long bizFlag) {
		this.bizFlag = bizFlag;
	}

	/** 是否存在赠送 */
	public boolean hasFree() {
		return freePart > 0;
	}

	/** 是否已充值过 */
	public boolean hasRecharged() {
		return hasFlag(BIZ_FLAG_RECHARGED);
	}

	/** 是否充值过钻石 */
	public boolean hasCoinRecharged(){
		return totalRecharge.compareTo(BigDecimal.ZERO) > 0;
	}

	/**
	 * 操作赠送额度
	 *
	 * @param op 运算符
	 * @param money 指定的额度
	 */
	public void opFreeAmount(final char op, final Integer money) {
		freePart = calc(freePart, op, money);
	}

	public boolean hasNoEnough(Integer coin) {
		return activeAmount < coin;
	}

	public <T> Messager<T> responseForNoBalance() {
		// return hasRecharged() ? Messager.status(MessagerStatus.LESS_COIN) : Messager.status(MessagerStatus.NO_COIN);
		WesKit wesKit = WesKit.ofIdWesKit(this.userId);
		if (wesKit.isInterior()) {
			return Messager.status(hasCoinRecharged() ? MessagerStatus.LESS_COIN : MessagerStatus.NO_COIN);
		}
		return Messager.status(MessagerStatus.LESS_COIN);
	}

	public static Map<String, Object> asEmbed(UserCoin source) {
		return asEmbed(source, t -> CollectionUtil.ofHashMap(
				"id", t.getId(),
				"activeAmount", t.getActiveAmount()
		));
	}

	public static Map<String, Object> asEmbedInfo(UserCoin source) {
		return asEmbed(source, t -> CollectionUtil.ofHashMap(
				"id", t.getId(),
				"totalAmount", t.getTotalAmount(),
				"activeAmount", t.getActiveAmount(),
				"frozenAmount", t.getFrozenAmount(),
				"freePart", t.getFreePart(),
				"totalRecharge", t.getTotalRecharge(),
				"allCoinRecharge", t.getAllCoinRecharge()
		));
	}

	public static final String USER_ID = "user_id";
	public static final String TOTAL_AMOUNT = "total_amount";
	public static final String ACTIVE_AMOUNT = "active_amount";
	public static final String FROZEN_AMOUNT = "frozen_amount";
	public static final String TOTAL_RECHARGE = "total_recharge";
	public static final String ALL_COIN_RECHARGE = "all_coin_recharge";
	public static final String BIZ_FLAG = "biz_flag";
	public static final String FREE_PART = "free_part";

}
